package com.springcloud.sc.ucpv5.client.application.message.connect;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;

import com.springcloud.sc.ucpv5.client.application.message.MessageService;
import com.springcloud.sc.ucpv5.client.application.util.Constant;
import com.springcloud.sc.ucpv5.client.common.CmdDefine;
import com.springcloud.sc.ucpv5.client.commondata.data.HertHandleMsg;
import com.springcloud.sc.ucpv5.client.commondata.idl.sj3.MsgHeader;
import com.springcloud.sc.ucpv5.client.commondata.idl.sj3.MsgHeaderHolder;
import com.springcloud.sc.ucpv5.client.module.datamanager.BaseDataManager;
import com.springcloud.sc.ucpv5.client.util.CorbarUtil;
import sun.net.ConnectionResetException;
import com.springcloud.sc.ucpv5.client.application.message.MessageServiceException;
import com.springcloud.sc.ucpv5.client.application.message.type.shortType.UnShort_Wrap;

public class TcpConnect extends ConnectFather {
    private static ShakeHandThread shakeHandThread = new ShakeHandThread();

    /**
     * 当前登录IP和port
     */
    private String currentIP = "";
    private int currentPort = 0;
    private Socket clientSocket;
    private InputStream in;
    private OutputStream out;

    private int localPort = 0;

    /**
     * 
     * 
     */
    public int internalInit(String strServerIP, final int iServerPort,  boolean isReconnect) throws MessageServiceException {

	currentIP = strServerIP;
	currentPort = iServerPort;

	try {
	    try {
		clientSocket = new Socket();
		clientSocket.setReceiveBufferSize(1024 * 1024);// 设置缓冲区大小
		clientSocket.setKeepAlive(true);

		InetSocketAddress inetSocketAddress = new InetSocketAddress(currentIP, currentPort);
		clientSocket.connect(inetSocketAddress, 5 * 1000);// 设置应答响应时间
	    } catch (Exception e) {
		try {
		    // 再做一次自动的尝试, 不根据本机ip
		    clientSocket = new Socket();
		    clientSocket.setReceiveBufferSize(1024 * 1024);// 设置缓冲区大小
		    clientSocket.setKeepAlive(true);

		    InetSocketAddress inetSocketAddress = new InetSocketAddress(currentIP, currentPort);
		    clientSocket.connect(inetSocketAddress, 5 * 1000);// 设置应答响应时间
		} catch (Exception e1) {
		    // e.printStackTrace();
		    return ERROR_CODE_CONNECT_FAIL;
		}
	    }

	    // System.out.println("本地ip信息:" +
	    // clientSocket.getLocalAddress().getHostAddress()+ ":" +
	    // clientSocket.getLocalPort());

	    localPort_alive = clientSocket.getLocalPort();
	    if (!isReconnect) {
		localPort = localPort_alive;
	    }

	    if (!isLocalPortRight()) {
		// 出现端口不一致情况
		return ERROR_CODE_CONNECT_FAIL;
	    }

	    in = clientSocket.getInputStream();
	    out = clientSocket.getOutputStream();

	    clientSocket.setSoTimeout(0);

	    // 消息接受流程
	    startReadThread();

	    shakeHandThread.setShakeHandTime(0);
	    return 0;
	    // return tmpresult.getRetCode();
	} catch (Exception ex) {
	    return ERROR_CODE_CONNECT_FAIL;
	}
    }

    private int localPort_alive = -1;
    public boolean isLocalPortRight() {
	if (localPort_alive != localPort) {
	    System.out.println("出现端口不一致情况!!!!!!!!");
	}
	return localPort_alive == localPort;
    }

    public boolean isDatAvailable() {
	try {
	    return in.available() > 0;
	} catch (Exception e) {
	    // TODO: handle exception
	}

	return false;
    }

    public int writeByteMsg(byte[] content) {
	if (clientSocket == null || clientSocket.isOutputShutdown() || clientSocket.isClosed()) {
	    return ERROR_CODE_SOCKET_SHUTDOWN;
	}

	ByteArrayOutputStream outStream = new ByteArrayOutputStream();
	try {

	    outStream.write(SOCKET_MSG_BEGIN);
	    // 写消息长度
	    outStream.write(UnShort_Wrap.packUnShort((short) (content.length + SOCKET_MSG_LENGTH), SOCKET_MSG_LENGTH, false));
	    // 写消息内容
	    outStream.write(content);

	    outStream.write(SOCKET_MSG_END);

	    out.write(outStream.toByteArray());

	    out.flush();

	} catch (ConnectionResetException exp) {
	    // exp.printStackTrace();
	    return ERROR_CODE_SOCKET_SHUTDOWN;
	} catch (SocketException exp) {
	    // exp.printStackTrace();
	    // try {
	    // clientSocket.close();
	    // } catch (IOException e) {
	    // // TODO 自动生成 catch 块
	    // e.printStackTrace();
	    // }
	    return ERROR_CODE_SOCKET_SHUTDOWN;
	} catch (Throwable exp) {
	    // exp.printStackTrace();
	    return ERROR_CODE_WRITE_SOCKET_FAIL;
	} finally {
	    try {
		outStream.close();
	    } catch (IOException e) {
		// e.printStackTrace();
	    }
	}

	return 0;
    }


    public void close() {
	if (out != null)
	    try {
		out.close();
		out = null;
	    } catch (IOException e1) {
		e1.printStackTrace();
	    }
	if (in != null)
	    try {
		in.close();
		in = null;
	    } catch (IOException e2) {
		e2.printStackTrace();
	    }
	if (clientSocket != null) {
	    try {
		clientSocket.close();
		clientSocket = null;
	    } catch (IOException e) {
		e.printStackTrace();
	    }
	}
	try {
	    shakeHandThread.stop();
	} catch (Exception e) {
	    // TODO: handle exception
	}
    }

    public boolean checkConnectOk() {
	if (clientSocket == null) {
	    return false;
	}
	if (clientSocket.isClosed()) {
	    return false;
	}
	return clientSocket.isConnected();
    }

    public void setConnnectClose() {
	try {
		close();
	} catch (Exception e) {
	    // TODO: handle exception
	}
    }
    
    public byte[] readSocket(int len) {
	ByteArrayOutputStream outStream = new ByteArrayOutputStream();
	try {
	    while (outStream.size() < len) {
		byte[] buf = new byte[len - outStream.size()];
		int rendLen = in.read(buf);
		outStream.write(buf, 0, rendLen);
	    }
	} catch (Exception e) {
	    // TODO: handle exception
	}

	return outStream.toByteArray();
    }

    public void doDataToServer(MessageData messageData) {
	try {
	   MsgHeader msgHeader = (MsgHeader) messageData.header.dataChangeCommonToCorbarData();
	    try {
		if (messageData.header.SessionID != getSessionId()) {
		    // 非当前登录需要的登录消息, 丢弃
		    // return;
		}

		com.google.protobuf.Message value = messageData.message.dataChangeCommonToProBufData();
		org.omg.CORBA.portable.Streamable holder = messageData.message.dataChangeCommonToCorbarDataHolder();
		msgHeader.MsgContent = CorbarUtil.struct2Byte(holder);

		MsgHeaderHolder headHolder = new MsgHeaderHolder();
		headHolder.value = msgHeader;

		// 后台发送
//		if (msgHeader.CmdID == Constant.CMD_COMMUNICATION_SHAKEHAND) {
//		    LogManager.debugInfo("!!!!!!!!!!!前台发送握手信息 " + DateToolUtil.getCurTime());
//		}

		writeByteMsg(CorbarUtil.struct2Byte(headHolder));
	    } catch (Exception e) {
		e.printStackTrace();
	    }
	} catch (Exception e) {
	    // TODO: handle exception
	}
    }

    public void doDataFromServer(Object msg) {
	try {
	    byte[] content = (byte[]) msg;
	    com.springcloud.sc.ucpv5.client.commondata.data.MsgHeader header = new com.springcloud.sc.ucpv5.client.commondata.data.MsgHeader();
	    header.dataContentDataToCommon(content);

//	    if (header.CmdID == Constant.CMD_COMMUNICATION_SHAKEHAND) {
//		LogManager.debugInfo("!!!!!!!!!!!前台收到握手信息 " + DateToolUtil.getCurTime());
//	    }

	    // LogManager.debugInfo("收到回应包:" + header.CmdID);
	    // wsy 20180725 如果上报消息的节点在服务器无法找到, 则丢弃
	    if (header.CmdID != CmdDefine.CMD_User_Login && header.CmdID != CmdDefine.CMD_User_Login_regcheck && header.CmdID != CmdDefine.CMD_User_Login_md5
		    && header.CmdID != CmdDefine.CMD_User_Login_md5_check) {
		if (BaseDataManager.getInstance().nodeGet(header.NodeNumber) == null) {
		    return;
		}
	    }

	    if (header.CmdID == CmdDefine.CMD_User_Logout) { // 如果登录消息响应用的话，把相关信息记录起来
		// 记录握手成功时间
		shakeHandThread.setShakeHandTime(0);
		shakeHandThread.stop();
		return;

	    } else if (header.CmdID == Constant.CMD_COMMUNICATION_SHAKEHAND) {
		try {
		    HertHandleMsg holder = new HertHandleMsg();
		    holder.dataContentDataToCommon(header.MsgContent);
		    //LogManager.debugInfo("!!!!!!!!!!!收到握手消息返回  结果:" + holder.reason + " " + DateToolUtil.getCurTime());

		    // if (holder != null && holder.reason == 1) {
		    // shakeHandThread.shakeHand(2);
		    // shakeHandThread.setShakeHandTime(System.currentTimeMillis());
		    // }
		    shakeHandThread.shakeHand(2);
		    shakeHandThread.setShakeHandTime(System.currentTimeMillis());
		    // TODO 握手消息处理
		} catch (Throwable e) {
		    e.printStackTrace();
		}

		return;
	    }
	    MessageService.getInstance().putMessage(header);

	} catch (Exception e) {
	    e.printStackTrace();
	}
    }

    /**
     * 启动握手, 在系统登录成功后启动
     */
    public void checkShakeHand() {
	try {
	    // 记录握手成功时间
	    shakeHandThread.setShakeHandTime(0);
	    shakeHandThread.beginShakeHands();
	} catch (Exception e) {
	    // TODO: handle exception
	}
    }
}
